package com.ruoyi.web.controller.common;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.minio.MinIOUtils;
import com.ruoyi.common.utils.Mp3AgicUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileTypeUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.file.VideoUtils;
import com.ruoyi.framework.util.ShiroUtils;
import com.ruoyi.system.domain.SysFileInfo;
import com.ruoyi.system.service.ISysFileInfoService;
import lombok.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 文件对象存储
 *
 * @author Licl
 */
@Controller
@RequestMapping("/file")
public class FileController {

    @Autowired
    private ISysFileInfoService sysFileInfoService;

    static List<String> suffixList = Arrays.asList("doc", "docx", "ppt", "pptx", "xls", "xlxs");

    @PostMapping("/uploadFiles")
    @ResponseBody
    public AjaxResult uploadFiles(@RequestParam(value = "file", required = false) MultipartFile[] file, String groupId) {
        AjaxResult error = getAjaxResult(file, groupId);
        if (error != null) {
            return error;
        }
        try {
            long sizeSum = 0L;
            // fileUUID
            if (StringUtils.isEmpty(groupId) || StringUtils.isNull(groupId)) {
                groupId = UUID.randomUUID().toString();
            }
            // 上传并返回新文件名称
            List<SysFileInfo> sysFileInfoList = new ArrayList<>();
            for (MultipartFile files : file) {
                SysFileInfo build = buildSysFileInfo(files, groupId);
                sizeSum += build.getFileSize();
                sysFileInfoList.add(build);
            }
            return getAjaxResult(file, groupId, sizeSum, sysFileInfoList);
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    private AjaxResult getAjaxResult(@RequestParam(value = "file", required = false) MultipartFile[] files, String groupId, long sizeSum, List<SysFileInfo> sysFileInfoList) {
        boolean saveBatch = sysFileInfoService.saveBatch(sysFileInfoList);
        if (saveBatch) {
            AjaxResult ajax = AjaxResult.success();
            ajax.put("sizeSum", sizeSum);
            ajax.put("fileCount", files.length);
            ajax.put("groupId", groupId);
            ajax.put("sysFileInfos", sysFileInfoList);
            return ajax;
        } else {
            return AjaxResult.error("上传异常！");
        }
    }

    private AjaxResult getAjaxResult(MultipartFile[] files, String groupId) {
        for (MultipartFile file : files) {
            String suffix = FileUtil.getSuffix(file.getOriginalFilename());
            if (suffixList.contains(suffix)) {
                return AjaxResult.error("请转为PDF再上传！");
            }
        }
        if (files.length == 0) {
            AjaxResult ajax = AjaxResult.success();
            ajax.put("groupId", groupId);
            return ajax;
        }
        return null;
    }

//    @PostMapping("/uploadFilesUnlimitedFileTypes")
//    @ResponseBody
    @Deprecated
    public AjaxResult uploadFilesUnlimitedFileTypes(@RequestParam(value = "file", required = false) MultipartFile[] files, String groupId) {
        if (files.length == 0) {
            AjaxResult ajax = AjaxResult.success();
            ajax.put("groupId", groupId);
            return ajax;
        }
        try {
            long sizeSum = 0L;
            // fileUUID
            if (StringUtils.isEmpty(groupId) || StringUtils.isNull(groupId)) {
                groupId = UUID.randomUUID().toString();
            }
            // 上传并返回新文件名称
            List<SysFileInfo> sysFileInfoList = new ArrayList<>();
            for (MultipartFile file : files) {
                String ossKey = IdUtil.simpleUUID();
                MinIOUtils.putObject(ossKey, file);

                String originalFilename = file.getOriginalFilename();
                String fileSuffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
                long fileSize = file.getSize();
                SysFileInfo build = SysFileInfo.builder()
                        .fileName(originalFilename)
                        .fileSuffix(fileSuffix)
                        .fileType(FileTypeUtils.getFileType(fileSuffix))
                        .ossKey(ossKey)
                        .fileSize(fileSize)
                        .groupId(groupId)
                        .filePath(FileUtils.getFileUrl(ossKey))
                        .build();

                sizeSum += fileSize;
                sysFileInfoList.add(build);
            }
            return getAjaxResult(files, groupId, sizeSum, sysFileInfoList);
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }


    /**
     * 上传单文件
     *
     * @param files 文件
     * @return 返回URL
     */
    @PostMapping("/upload")
    @ResponseBody
    public AjaxResult upload(@RequestParam(value = "files", required = false) MultipartFile[] files) throws Exception {
        for (MultipartFile file : files) {
            String suffix = FileUtil.getSuffix(file.getOriginalFilename());
            if (suffixList.contains(suffix)) {
                return AjaxResult.error("请转为PDF再上传！");
            }
        }
        List<String> urls = new ArrayList<>();
        for (MultipartFile file : files) {
            String key = IdUtil.simpleUUID();
            FileUtils.putObject(key, file);
            String url = FileUtils.getFileUrl(key);
            urls.add(url);
        }
        return AjaxResult.ok().proPut("urls", urls).build();
    }

//    @PostMapping("/uploadAliAndMinio")
//    @ResponseBody
    @Deprecated
    public AjaxResult uploadAliAndMinio(@RequestParam(value = "file", required = false) MultipartFile[] files, String groupId) {
        AjaxResult error = getResult(files, groupId);
        if (error != null) {
            return error;
        }
        try {
            long sizeSum = 0L;
            // fileUUID
            if (StringUtils.isEmpty(groupId) || StringUtils.isNull(groupId)) {
                groupId = UUID.randomUUID().toString();
            }
            String loginName = ShiroUtils.getLoginName();
            // 上传并返回新文件名称
            List<SysFileInfo> sysFileInfoList = new ArrayList<>();
            for (MultipartFile file : files) {
                String ossKey = IdUtil.simpleUUID();
                MinIOUtils.putObject(ossKey, file);
                String originalFilename = file.getOriginalFilename();
                assert originalFilename != null;
                String fileSuffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
                long fileSize = file.getSize();
                SysFileInfo build = SysFileInfo.builder()
                        .fileName(originalFilename)
                        .fileSuffix(fileSuffix)
                        .fileType(FileTypeUtils.getFileType(fileSuffix))
                        .ossKey(ossKey)
                        .fileSize(fileSize)
                        .groupId(groupId)
                        .filePath(FileUtils.getFileUrl(ossKey))
                        .build();

                sizeSum += fileSize;
                sysFileInfoList.add(build);
            }
            return getAjaxResult(files, groupId, sizeSum, sysFileInfoList);
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    private AjaxResult getResult(MultipartFile[] files, String groupId) {
        for (MultipartFile file : files) {
            String suffix = FileUtil.getSuffix(file.getOriginalFilename());
            if (suffixList.contains(suffix)) {
                return AjaxResult.error("请转为PDF再上传！");
            }
        }
        if (files.length == 0) {
            AjaxResult ajax = AjaxResult.success();
            ajax.put("groupId", groupId);
            return ajax;
        }
        return null;
    }

    @PostMapping("/wangEditorUploadImg")
    @ResponseBody
    public Map<String, Object> wangEditorUploadImg(@RequestParam(value = "files") MultipartFile[] files) throws Exception {
        Map<String, Object> map = new HashMap<>();
        map.put("errno", 0);
        List<WangEditorImg> imgList = Arrays.stream(files).map(e -> {
            WangEditorImg build = WangEditorImg.builder()
                    .alt(e.getOriginalFilename())
                    .href("")
                    .build();
            try {
                build.setUrl(MinIOUtils.putObjectRetPath(e));
                return build;
            } catch (Exception exception) {
                map.put("errno", 500);
                exception.printStackTrace();
            }
            return build;
        }).collect(Collectors.toList());
        map.put("data", imgList);
        return map;
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    static class WangEditorImg {
        private String url;
        private String alt;
        private String href;

    }

    @PostMapping("/froalaUpload")
    @ResponseBody
    public Map<String, String> froalaUpload(@RequestParam(value = "file") MultipartFile file) throws Exception {
        HashMap<String, String> map = new HashMap<>();
        map.put("link", MinIOUtils.putObjectRetPath(file));
        return map;
    }

    @PostMapping("/uploadFile")
    @ResponseBody
    public AjaxResult uploadFile(@RequestParam(value = "file", required = false) MultipartFile file, String groupId) {
        try {
            // fileUUID
            if (StringUtils.isEmpty(groupId) || StringUtils.isNull(groupId)) {
                groupId = UUID.randomUUID().toString();
            }
            // 上传并返回新文件名称
            SysFileInfo build = buildSysFileInfo(file, groupId);
            // 获取音视频时长
            long duration = getDuration(file);

            boolean saveBatch = sysFileInfoService.save(build);
            if (saveBatch) {
                return AjaxResult.ok().put("groupId", groupId)
                        .put("url", build.getFilePath())
                        .put("duration", duration)
                        .build();
            } else {
                return AjaxResult.error("上传异常！");
            }
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    private SysFileInfo buildSysFileInfo(MultipartFile file, String groupId) throws Exception {
        String ossKey = IdUtil.simpleUUID();
        FileUtils.putObject(ossKey, file);
        String originalFilename = file.getOriginalFilename();
        assert originalFilename != null;
        String fileSuffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        long fileSize = file.getSize();
        return SysFileInfo.builder()
                .fileName(originalFilename)
                .fileSuffix(fileSuffix)
                .fileType(FileTypeUtils.getFileType(fileSuffix))
                .ossKey(ossKey)
                .fileSize(fileSize)
                .groupId(groupId)
                .filePath(FileUtils.getFileUrl(ossKey))
                .build();
    }


    @SneakyThrows
    public long getDuration(MultipartFile file){
        // 判断文件是视频还是音频
        String contentType = file.getContentType();
        assert contentType != null;
        boolean audio = contentType.contains("audio");
        boolean video = contentType.contains("video");
        if (!audio && !video){
            return 0;
        }
        String tmpDirPath = FileUtil.getTmpDirPath();
        String path = tmpDirPath + "yuan-" + RandomUtil.randomString(8) + ".tmp";
        File file1 = FileUtil.file(path);
        File tempFile = FileUtil.createTempFile(file1);
        file.transferTo(tempFile);
        long duration = 0;
        if (audio){
            duration = Mp3AgicUtil.duration(tempFile.getPath());
        }
        if (video) {
            duration = VideoUtils.getVideoTime(tempFile.getPath());
        }
        FileUtil.del(path);
        return duration;
    }

    @PostMapping("/saveSimpleUpload")
    @ResponseBody
    public JSONObject saveSimpleUpload(String name, String ossKey, Long size){
        String fileSuffix = FileUtil.getSuffix(name);
        String groupId = UUID.randomUUID().toString();
        String fileUrl = FileUtils.getFileUrl(ossKey);
        SysFileInfo build = SysFileInfo.builder()
                .fileName(name)
                .fileSuffix(fileSuffix)
                .fileType(FileTypeUtils.getFileType(fileSuffix))
                .ossKey(ossKey)
                .fileSize(size)
                .groupId(groupId)
                .filePath(fileUrl)
                .build();
        boolean save = sysFileInfoService.save(build);
        return JSONUtil.createObj().putOpt("flag", save)
                .putOpt("groupId", groupId)
                .putOpt("filePath", fileUrl);
    }

}
